﻿using System;
using System.Collections.Generic;
using System.Linq;
using BearUtil;
using BearUtil.Hidden;
using DocumentFormat.OpenXml.Drawing;
using Sirenix.Utilities;
using UnityEngine;
using Path = System.IO.Path;

// dialog_moduel 数据类
public class DialogFormatUtil
{
    /// <summary>
    /// 设置类型
    /// </summary>
    /// <param name="nt"></param>
    public static void SetData(out DialogData data, BearNode node)
    {
        data = new DialogData();
        var dataType = node.GetType();

        //特殊处理几个不好处理的节点：StartNode, EndNode, TalkNode
        int type = (int) dataType.GetField("type").GetValue(node);
        data.type = type;
        if (type == (int) NodeType.START ||
            type == (int) NodeType.END)
        {
        }
        else if (type == (int) NodeType.TALK)
        {
            setTalkData(data, node as TalkNode);
        }
        else if (type == (int) NodeType.CHOICE)
        {
            setChoice(data, node as ChoiceNode);
        }
        else
        {
            var infos = dataType.GetFields();
            for (int i = 0; i < infos.Length; i++)
            {
                try
                {
                    var info = infos[i];
                    // startwith "_" 表示不进入数据分析过程，自定义属性的辅助属性需求
                    if (!info.DeclaringType.Name.Equals(dataType.Name) ||
                        info.FieldType.Name.ToLower().Equals("audioclip") || info.Name.StartsWith("_"))
                        continue;

                    // 兼容旧代码
                    if (info.FieldType.Name.ToLower().Equals("vector2"))
                    {
                        // 临时跳过 PlayItemMerger
                        if (infos[i].Name.Equals("ProductPos"))
                            continue;

                        var propX = info.Name + "_x";
                        var propY = info.Name + "_y";
                        Vector2 pos = (Vector2) info.GetValue(node);
                        data.GetType().GetField(propX).SetValue(data, pos.x);
                        data.GetType().GetField(propY).SetValue(data, pos.y);
                    }
                    // 兼容旧代码
                    else if (info.FieldType.Name.ToLower().Equals("node"))
                    {
                        var nodes = (BearNode[]) info.GetValue(node);
                        List<int> indexs = new List<int>();
                        for (int j = 0; j < nodes.Length; j++)
                        {
                            indexs.Add(nodes[j].index);
                        }

                        data.GetType().GetField(info.Name).SetValue(data, indexs);
                    }
                    else
                    {
                        // 临时跳过 PlayItemMerger
                        if (infos[i].Name.Equals("Product") || infos[i].Name.Equals("Material1") ||
                            infos[i].Name.Equals("Material2") || infos[i].Name.First().Equals("_"))
                            continue;

                        data.GetType().GetField(info.Name).SetValue(data, info.GetValue(node));
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError(string.Format("[DialogDataFormat] error info:{0} : {1} ", infos[i].Name,
                        data.GetType().Name));
                    Debug.LogError(e);
                }
            }
        }

        // 新版本，要求增加后缀
#if RECONSTRUCT_VERSION
        reconstructVersion_AddExt(data);
#endif

        data.id = node.index;
        data.back_step = (node as BearNode).isSaved ? 1 : 0;
        // choice(2) 和 end(-1) 节点不用 chlidNode
        if (data.type != (int) NodeType.CHOICE &&
            data.type != (int) NodeType.END)
            setChildNode(data, node);
    }

    // 设置子节点数据
    private static void setChildNode(DialogData data, BearNode node)
    {
        List<int> children = new List<int>();
        var nextPort = node.Ports.Where(port => port.fieldName.Equals("next"))?.First();
        if (nextPort != null && nextPort.ConnectionCount > 0)
        {
            var connections = nextPort.GetConnections();
            for (int i = 0; i < connections.Count; i++)
            {
                var bn = (connections[i].node as BearNode);
                if (bn != null)
                {
                    children.Add(bn.index);
                }
                else
                {
                    var mn = connections[i].node as MergeNode;
                    if (mn != null)
                    {
                        children.Add(mn.GetNext().index);
                    }
                }
            }

            // 分支节点一定大于主干节点 index，因为系统中的运行器不是我写的，所以这里用最简单的方法兼容一下
            children.Sort();
        }

        data.child_node = new int[1][];
        data.child_node[0] = children.ToArray();
    }

    private static void setTalkData(DialogData data, TalkNode tn)
    {
        if (tn.actor != null)
        {
            data.role_id = tn.actor.role_id;
            data.role_name = tn.role_name;
            data.icon_portrait = tn.icon_portrait == null || tn.icon_portrait.Equals("")
                ? new string[] {""}
                : new string[] {"#" + tn.icon_portrait};

            data.is_show_scene = tn.showOnScene;
        }

        data.scene_bubble = (int) tn.scene_bubble;
        data.lines_bubble = (int) tn.lines_bubble;
        data.icon_pic = tn.show_pic;
        data.icon_bg = tn.show_bg;
        data.lines_speed = (int) tn.FontSpeed;
        data.portrait_direction = (int) tn.portrait_direction;
        data.lines = tn.lines;

        data.voice = !tn.VoiceClip.Equals("null") ? tn.VoiceClip : "";
        // 临时操作
        if (!string.IsNullOrEmpty(tn.actor?.spine_name))
        {
            data.portrait = $"ui_plot_{tn.actor?.spine_name}.prefab";
            var animName = tn.icon_portrait.Split('_');
            if (animName.Length < 2)
            {
                Debug.LogError("角色立绘丢失: " + tn.graph.name + ": " + tn.name);
                return;
            }

            data.portraitAnim = $"{animName[animName.Length - 2]}_{animName.Last()}";
        }

        // if (tn.audioData.SFX != null && !tn.audioData.SFX.name.Equals("null"))
        //      = tn.audioData.SFX.name;
    }

    /// <summary>
    /// 选项
    /// </summary>
    /// <param name="node"></param>
    private static void setChoice(DialogData data, ChoiceNode node)
    {
        var outputs = node.Ports.Where(p => p.fieldName.Contains("output")).ToList();

        List<int> subIndex = new List<int>();
        for (var i = 0; i < outputs.Count; i++)
        {
            var output = outputs[i];
            var tmp = output.Connection?.node;
            var bn = (tmp as BearNode);
            if (bn == null)
                bn = (tmp as MergeNode)?.Outputs?.First().Connection?.node as BearNode;

            if (bn != null)
                subIndex.Add(bn.index);
        }

        data.child_node = new int[subIndex.Count][];
        for (int i = 0; i < subIndex.Count(); i++)
        {
            data.child_node[i] = new int[] {subIndex[i]};
        }

        data.type = node.type;
        // 赋值
        data.choose_text = node.GetLines();
    }

    /// <summary>
    /// 增加数据后缀
    /// </summary>
    /// <param name="data"></param>
    private static void reconstructVersion_AddExt(DialogData data)
    {
        string prefabExt = ".prefab";
        string animExt = ".anim";

        // audio clip 
        if (!string.IsNullOrEmpty(data.voice))
        {
            if (!Path.HasExtension(data.voice))
                data.voice += ".ogg";
        }
        else if (!string.IsNullOrEmpty(data.effect_id))
        {
            if (!Path.HasExtension(data.effect_id))
                data.effect_id = $"{data.effect_id.Trim()}{prefabExt}";
        }
        else if (!string.IsNullOrEmpty(data.generate_anime))
        {
            if (!Path.HasExtension(data.generate_anime))
                data.generate_anime = $"{data.generate_anime.Trim()}{prefabExt}";
        }
        else if (!string.IsNullOrEmpty(data.illustration_name))
        {
            if (!Path.HasExtension(data.illustration_name))
                data.illustration_name = $"{data.illustration_name.Trim()}{prefabExt}";
        }
        else if (!string.IsNullOrEmpty(data.expression_name))
        {
            if (!Path.HasExtension(data.expression_name))
                data.expression_name = $"{data.expression_name.Trim()}{prefabExt}";
        }
        else if (!string.IsNullOrEmpty(data.destroy_anime))
        {
            if (!Path.HasExtension(data.destroy_anime))
                data.destroy_anime = $"{data.destroy_anime.Trim()}{prefabExt}";
        }
        else if (!string.IsNullOrEmpty(data.shake_anime_name))
        {
            if(!Path.HasExtension(data.shake_anime_name))
                data.shake_anime_name = $"{data.shake_anime_name.Trim()}{animExt}";
        }
    }
}